blob: 0b870731513740fc9e0d0d96d7f6694b79927f63 [file] [log] [blame]
David Pursehouse8898e2f2012-11-14 07:51:03 +09001#!/usr/bin/env python
Mike Frysingerf6013762019-06-13 02:30:51 -04002# -*- coding:utf-8 -*-
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07003
Mike Frysinger87fb5a12019-06-13 01:54:46 -04004"""Repo launcher.
5
6This is a standalone tool that people may copy to anywhere in their system.
7It is used to get an initial repo client checkout, and after that it runs the
8copy of repo in the checkout.
9"""
10
Mike Frysingerc92ce5c2019-06-13 01:14:23 -040011from __future__ import print_function
12
Mark E. Hamilton4088eb42016-02-10 10:44:30 -070013# repo default configuration
14#
Mark E. Hamilton55536282016-02-03 15:49:43 -070015import os
16REPO_URL = os.environ.get('REPO_URL', None)
17if not REPO_URL:
18 REPO_URL = 'https://gerrit.googlesource.com/git-repo'
David Pursehouse8f62fb72012-11-14 12:09:38 +090019REPO_REV = 'stable'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070020
21# Copyright (C) 2008 Google Inc.
22#
23# Licensed under the Apache License, Version 2.0 (the "License");
24# you may not use this file except in compliance with the License.
25# You may obtain a copy of the License at
26#
27# http://www.apache.org/licenses/LICENSE-2.0
28#
29# Unless required by applicable law or agreed to in writing, software
30# distributed under the License is distributed on an "AS IS" BASIS,
31# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32# See the License for the specific language governing permissions and
33# limitations under the License.
34
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070035# increment this whenever we make important changes to this script
Mike Frysingeree451f02020-02-04 00:00:08 -050036VERSION = (2, 0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070037
38# increment this if the MAINTAINER_KEYS block is modified
Mike Frysingerf5525fb2020-02-04 00:01:00 -050039KEYRING_VERSION = (2, 0)
Mike Frysingere4433652016-09-13 18:06:07 -040040
41# Each individual key entry is created by using:
42# gpg --armor --export keyid
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070043MAINTAINER_KEYS = """
44
45 Repo Maintainer <repo@android.kernel.org>
46-----BEGIN PGP PUBLIC KEY BLOCK-----
47Version: GnuPG v1.4.2.2 (GNU/Linux)
48
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
84=CMiZ
85-----END PGP PUBLIC KEY BLOCK-----
86"""
87
Mark E. Hamilton4088eb42016-02-10 10:44:30 -070088GIT = 'git' # our git command
Mike Frysinger655aedd2020-02-04 00:02:18 -050089MIN_GIT_VERSION = (2, 10, 2) # minimum supported git version
Mark E. Hamilton4088eb42016-02-10 10:44:30 -070090repodir = '.repo' # name of repo's private directory
91S_repo = 'repo' # special repo repository
92S_manifests = 'manifests' # special manifest repository
93REPO_MAIN = S_repo + '/main.py' # main script
Eli Ribbled4b13c22018-12-18 21:21:12 -080094MIN_PYTHON_VERSION = (2, 7) # minimum supported python version
Simran Basi8ce50412015-08-28 14:25:44 -070095GITC_CONFIG_FILE = '/gitc/.config'
Dan Willemsen745b4ad2015-10-06 15:23:19 -070096GITC_FS_ROOT_DIR = '/gitc/manifest-rw/'
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070097
98
Mike Frysinger6db1b9e2019-07-10 15:32:36 -040099import collections
David Jamesbf79c662013-12-26 14:20:13 -0800100import errno
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700101import optparse
Renaud Paquay35d22212016-11-01 11:24:52 -0700102import platform
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700103import re
Mitchel Humpheryseb5acc92014-03-12 10:48:15 -0700104import shutil
Sarah Owens60798a32012-10-25 17:53:09 -0700105import stat
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700106import subprocess
107import sys
David Pursehouse59bbb582013-05-17 10:49:33 +0900108
109if sys.version_info[0] == 3:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700110 import urllib.request
111 import urllib.error
112else:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700113 import imp
David Pursehouse59bbb582013-05-17 10:49:33 +0900114 import urllib2
Sarah Owens1f7627f2012-10-31 09:21:55 -0700115 urllib = imp.new_module('urllib')
116 urllib.request = urllib2
117 urllib.error = urllib2
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700118
Conley Owens5e0ee142013-09-26 15:50:49 -0700119
Chirayu Desai51813df2013-04-16 19:36:09 +0530120# Python version check
121ver = sys.version_info
Chirayu Desai51813df2013-04-16 19:36:09 +0530122if (ver[0], ver[1]) < MIN_PYTHON_VERSION:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400123 print('error: Python version {} unsupported.\n'
124 'Please use Python {}.{} instead.'.format(
125 sys.version.split(' ')[0],
126 MIN_PYTHON_VERSION[0],
127 MIN_PYTHON_VERSION[1],
128 ), file=sys.stderr)
Chirayu Desai51813df2013-04-16 19:36:09 +0530129 sys.exit(1)
130
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700131home_dot_repo = os.path.expanduser('~/.repoconfig')
132gpg_dir = os.path.join(home_dot_repo, 'gnupg')
133
134extra_args = []
135init_optparse = optparse.OptionParser(usage="repo init -u url [options]")
136
137# Logging
138group = init_optparse.add_option_group('Logging options')
139group.add_option('-q', '--quiet',
140 dest="quiet", action="store_true", default=False,
141 help="be quiet")
142
143# Manifest
144group = init_optparse.add_option_group('Manifest options')
145group.add_option('-u', '--manifest-url',
146 dest='manifest_url',
147 help='manifest repository location', metavar='URL')
148group.add_option('-b', '--manifest-branch',
149 dest='manifest_branch',
150 help='manifest branch or revision', metavar='REVISION')
151group.add_option('-m', '--manifest-name',
152 dest='manifest_name',
153 help='initial manifest file', metavar='NAME.xml')
Ereth McKnight-MacNeil12ee5442018-12-19 21:28:35 -0800154group.add_option('--current-branch',
Naseer Ahmedf4dda9a2016-12-01 18:49:54 -0500155 dest='current_branch_only', action='store_true',
156 help='fetch only current manifest branch from server')
Shawn O. Pearcee284ad12008-11-04 07:37:10 -0800157group.add_option('--mirror',
158 dest='mirror', action='store_true',
David Pursehouse3794a782012-11-15 06:17:30 +0900159 help='create a replica of the remote repositories '
160 'rather than a client working directory')
Shawn O. Pearce88443382010-10-08 10:02:09 +0200161group.add_option('--reference',
162 dest='reference',
163 help='location of mirror directory', metavar='DIR')
Nikolai Merinov09f0abb2018-10-19 15:07:05 +0500164group.add_option('--dissociate',
165 dest='dissociate', action='store_true',
166 help='dissociate from reference mirrors after clone')
Doug Anderson49cd59b2011-06-13 21:42:06 -0700167group.add_option('--depth', type='int', default=None,
168 dest='depth',
169 help='create a shallow clone with given depth; see git clone')
Xin Li745be2e2019-06-03 11:24:30 -0700170group.add_option('--partial-clone', action='store_true',
171 dest='partial_clone',
172 help='perform partial clone (https://git-scm.com/'
173 'docs/gitrepository-layout#_code_partialclone_code)')
174group.add_option('--clone-filter', action='store', default='blob:none',
175 dest='clone_filter',
176 help='filter for use with --partial-clone [default: %default]')
Julien Campergue335f5ef2013-10-16 11:02:35 +0200177group.add_option('--archive',
178 dest='archive', action='store_true',
179 help='checkout an archive instead of a git repository for '
180 'each project. See git archive.')
Martin Kellye4e94d22017-03-21 16:05:12 -0700181group.add_option('--submodules',
182 dest='submodules', action='store_true',
183 help='sync any submodules associated with the manifest repo')
Colin Cross5acde752012-03-28 20:15:45 -0700184group.add_option('-g', '--groups',
Conley Owens971de8e2012-04-16 10:36:08 -0700185 dest='groups', default='default',
David Holmer0a1c6a12012-11-14 19:19:00 -0500186 help='restrict manifest projects to ones with specified '
187 'group(s) [default|all|G1,G2,G3|G4,-G5,-G6]',
Colin Cross5acde752012-03-28 20:15:45 -0700188 metavar='GROUP')
Conley Owensd21720d2012-04-16 11:02:21 -0700189group.add_option('-p', '--platform',
190 dest='platform', default="auto",
Conley Owensc9129d92012-10-01 16:12:28 -0700191 help='restrict manifest projects to ones with a specified '
Conley Owensd21720d2012-04-16 11:02:21 -0700192 'platform group [auto|all|none|linux|darwin|...]',
193 metavar='PLATFORM')
Hu xiuyun9711a982015-12-11 11:16:41 +0800194group.add_option('--no-clone-bundle',
195 dest='no_clone_bundle', action='store_true',
196 help='disable use of /clone.bundle on HTTP/HTTPS')
Naseer Ahmedf4dda9a2016-12-01 18:49:54 -0500197group.add_option('--no-tags',
198 dest='no_tags', action='store_true',
199 help="don't fetch tags in the manifest")
Doug Anderson49cd59b2011-06-13 21:42:06 -0700200
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700201
202# Tool
Shawn O. Pearcefd89b672009-04-18 11:28:57 -0700203group = init_optparse.add_option_group('repo Version options')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700204group.add_option('--repo-url',
205 dest='repo_url',
206 help='repo repository location', metavar='URL')
207group.add_option('--repo-branch',
208 dest='repo_branch',
209 help='repo branch or revision', metavar='REVISION')
210group.add_option('--no-repo-verify',
211 dest='no_repo_verify', action='store_true',
212 help='do not verify repo source code')
213
Victor Boivie841be342011-04-05 11:31:10 +0200214# Other
215group = init_optparse.add_option_group('Other options')
216group.add_option('--config-name',
217 dest='config_name', action="store_true", default=False,
218 help='Always prompt for name/e-mail')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700219
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700220
221def _GitcInitOptions(init_optparse_arg):
222 init_optparse_arg.set_usage("repo gitc-init -u url -c client [options]")
223 g = init_optparse_arg.add_option_group('GITC options')
Simran Basi1efc2b42015-08-05 15:04:22 -0700224 g.add_option('-f', '--manifest-file',
225 dest='manifest_file',
226 help='Optional manifest file to use for this GITC client.')
227 g.add_option('-c', '--gitc-client',
228 dest='gitc_client',
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700229 help='The name of the gitc_client instance to create or modify.')
Simran Basi1efc2b42015-08-05 15:04:22 -0700230
Simran Basi8ce50412015-08-28 14:25:44 -0700231_gitc_manifest_dir = None
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700232
233
Simran Basi8ce50412015-08-28 14:25:44 -0700234def get_gitc_manifest_dir():
235 global _gitc_manifest_dir
236 if _gitc_manifest_dir is None:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700237 _gitc_manifest_dir = ''
Simran Basi8ce50412015-08-28 14:25:44 -0700238 try:
239 with open(GITC_CONFIG_FILE, 'r') as gitc_config:
240 for line in gitc_config:
241 match = re.match('gitc_dir=(?P<gitc_manifest_dir>.*)', line)
242 if match:
243 _gitc_manifest_dir = match.group('gitc_manifest_dir')
244 except IOError:
Dan Willemsen2487cb72015-08-31 15:45:06 -0700245 pass
Simran Basi8ce50412015-08-28 14:25:44 -0700246 return _gitc_manifest_dir
247
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700248
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700249def gitc_parse_clientdir(gitc_fs_path):
250 """Parse a path in the GITC FS and return its client name.
251
252 @param gitc_fs_path: A subdirectory path within the GITC_FS_ROOT_DIR.
253
254 @returns: The GITC client name
255 """
256 if gitc_fs_path == GITC_FS_ROOT_DIR:
257 return None
258 if not gitc_fs_path.startswith(GITC_FS_ROOT_DIR):
259 manifest_dir = get_gitc_manifest_dir()
260 if manifest_dir == '':
261 return None
262 if manifest_dir[-1] != '/':
263 manifest_dir += '/'
264 if gitc_fs_path == manifest_dir:
265 return None
266 if not gitc_fs_path.startswith(manifest_dir):
267 return None
268 return gitc_fs_path.split(manifest_dir)[1].split('/')[0]
269 return gitc_fs_path.split(GITC_FS_ROOT_DIR)[1].split('/')[0]
270
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700271
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700272class CloneFailure(Exception):
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700273
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700274 """Indicate the remote clone of repo itself failed.
275 """
276
277
Simran Basi1efc2b42015-08-05 15:04:22 -0700278def _Init(args, gitc_init=False):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700279 """Installs repo by cloning it over the network.
280 """
Simran Basi1efc2b42015-08-05 15:04:22 -0700281 if gitc_init:
282 _GitcInitOptions(init_optparse)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700283 opt, args = init_optparse.parse_args(args)
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800284 if args:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700285 init_optparse.print_usage()
286 sys.exit(1)
287
288 url = opt.repo_url
289 if not url:
290 url = REPO_URL
291 extra_args.append('--repo-url=%s' % url)
292
293 branch = opt.repo_branch
294 if not branch:
295 branch = REPO_REV
296 extra_args.append('--repo-branch=%s' % branch)
297
298 if branch.startswith('refs/heads/'):
299 branch = branch[len('refs/heads/'):]
300 if branch.startswith('refs/'):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400301 print("fatal: invalid branch name '%s'" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700302 raise CloneFailure()
303
David Jamesbf79c662013-12-26 14:20:13 -0800304 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700305 if gitc_init:
Simran Basi8ce50412015-08-28 14:25:44 -0700306 gitc_manifest_dir = get_gitc_manifest_dir()
307 if not gitc_manifest_dir:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400308 print('fatal: GITC filesystem is not available. Exiting...',
309 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700310 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700311 gitc_client = opt.gitc_client
312 if not gitc_client:
313 gitc_client = gitc_parse_clientdir(os.getcwd())
314 if not gitc_client:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400315 print('fatal: GITC client (-c) is required.', file=sys.stderr)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700316 sys.exit(1)
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700317 client_dir = os.path.join(gitc_manifest_dir, gitc_client)
Simran Basi1efc2b42015-08-05 15:04:22 -0700318 if not os.path.exists(client_dir):
319 os.makedirs(client_dir)
320 os.chdir(client_dir)
321 if os.path.exists(repodir):
322 # This GITC Client has already initialized repo so continue.
323 return
324
David Jamesbf79c662013-12-26 14:20:13 -0800325 os.mkdir(repodir)
326 except OSError as e:
327 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400328 print('fatal: cannot make %s directory: %s'
329 % (repodir, e.strerror), file=sys.stderr)
David Pursehouse3794a782012-11-15 06:17:30 +0900330 # Don't raise CloneFailure; that would delete the
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700331 # name. Instead exit immediately.
332 #
333 sys.exit(1)
334
335 _CheckGitVersion()
336 try:
Sebastian Schuberth8f997b32020-01-20 11:42:48 +0100337 if opt.no_repo_verify:
338 do_verify = False
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700339 else:
Sebastian Schuberth8f997b32020-01-20 11:42:48 +0100340 if NeedSetupGnuPG():
341 do_verify = SetupGnuPG(opt.quiet)
342 else:
343 do_verify = True
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700344
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700345 dst = os.path.abspath(os.path.join(repodir, S_repo))
Hu xiuyun9711a982015-12-11 11:16:41 +0800346 _Clone(url, dst, opt.quiet, not opt.no_clone_bundle)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700347
Sebastian Schuberth8f997b32020-01-20 11:42:48 +0100348 if do_verify:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700349 rev = _Verify(dst, branch, opt.quiet)
350 else:
351 rev = 'refs/remotes/origin/%s^0' % branch
352
353 _Checkout(dst, branch, rev, opt.quiet)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200354
355 if not os.path.isfile(os.path.join(dst, 'repo')):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400356 print("warning: '%s' does not look like a git-repo repository, is "
357 "REPO_URL set correctly?" % url, file=sys.stderr)
Sebastian Schuberth993dcac2018-07-13 10:25:52 +0200358
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700359 except CloneFailure:
360 if opt.quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400361 print('fatal: repo init failed; run without --quiet to see why',
362 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700363 raise
364
365
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400366# The git version info broken down into components for easy analysis.
367# Similar to Python's sys.version_info.
368GitVersion = collections.namedtuple(
369 'GitVersion', ('major', 'minor', 'micro', 'full'))
370
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400371def ParseGitVersion(ver_str=None):
372 if ver_str is None:
373 # Load the version ourselves.
374 ver_str = _GetGitVersion()
375
Conley Owensff0a3c82014-01-30 14:46:03 -0800376 if not ver_str.startswith('git version '):
377 return None
378
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400379 full_version = ver_str[len('git version '):].strip()
380 num_ver_str = full_version.split('-')[0]
Conley Owensff0a3c82014-01-30 14:46:03 -0800381 to_tuple = []
382 for num_str in num_ver_str.split('.')[:3]:
383 if num_str.isdigit():
384 to_tuple.append(int(num_str))
385 else:
386 to_tuple.append(0)
Mike Frysinger6db1b9e2019-07-10 15:32:36 -0400387 to_tuple.append(full_version)
388 return GitVersion(*to_tuple)
Conley Owensff0a3c82014-01-30 14:46:03 -0800389
390
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400391def _GetGitVersion():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700392 cmd = [GIT, '--version']
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700393 try:
394 proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700395 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400396 print(file=sys.stderr)
397 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
398 print('fatal: %s' % e, file=sys.stderr)
399 print(file=sys.stderr)
400 print('Please make sure %s is installed and in your path.' % GIT,
401 file=sys.stderr)
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400402 raise
Shawn O. Pearce4fd38ec2012-06-05 07:55:07 -0700403
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700404 ver_str = proc.stdout.read().strip()
405 proc.stdout.close()
Shawn O. Pearce16191342008-10-28 08:33:34 -0700406 proc.wait()
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400407 return ver_str.decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700408
Mike Frysingerf88b2fe2019-07-10 15:37:43 -0400409
410def _CheckGitVersion():
411 try:
412 ver_act = ParseGitVersion()
413 except OSError:
414 raise CloneFailure()
415
Conley Owensff0a3c82014-01-30 14:46:03 -0800416 if ver_act is None:
Mike Frysinger4c263b52019-09-11 04:04:16 -0400417 print('fatal: unable to detect git version', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700418 raise CloneFailure()
419
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700420 if ver_act < MIN_GIT_VERSION:
David Pursehouse685f0802012-11-14 08:34:39 +0900421 need = '.'.join(map(str, MIN_GIT_VERSION))
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400422 print('fatal: git %s or later required' % need, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700423 raise CloneFailure()
424
425
Conley Owensc9129d92012-10-01 16:12:28 -0700426def NeedSetupGnuPG():
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700427 if not os.path.isdir(home_dot_repo):
428 return True
429
430 kv = os.path.join(home_dot_repo, 'keyring-version')
431 if not os.path.exists(kv):
432 return True
433
434 kv = open(kv).read()
435 if not kv:
436 return True
437
David Pursehouse685f0802012-11-14 08:34:39 +0900438 kv = tuple(map(int, kv.split('.')))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700439 if kv < KEYRING_VERSION:
440 return True
441 return False
442
443
Conley Owensc9129d92012-10-01 16:12:28 -0700444def SetupGnuPG(quiet):
David Jamesbf79c662013-12-26 14:20:13 -0800445 try:
446 os.mkdir(home_dot_repo)
447 except OSError as e:
448 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400449 print('fatal: cannot make %s directory: %s'
450 % (home_dot_repo, e.strerror), file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700451 sys.exit(1)
452
David Jamesbf79c662013-12-26 14:20:13 -0800453 try:
454 os.mkdir(gpg_dir, stat.S_IRWXU)
455 except OSError as e:
456 if e.errno != errno.EEXIST:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400457 print('fatal: cannot make %s directory: %s' % (gpg_dir, e.strerror),
458 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700459 sys.exit(1)
460
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800461 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300462 try:
463 env['GNUPGHOME'] = gpg_dir
464 except UnicodeEncodeError:
465 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700466
467 cmd = ['gpg', '--import']
468 try:
469 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700470 env=env,
471 stdin=subprocess.PIPE)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700472 except OSError as e:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700473 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400474 print('warning: gpg (GnuPG) is not available.', file=sys.stderr)
475 print('warning: Installing it is strongly encouraged.', file=sys.stderr)
476 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700477 return False
478
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400479 proc.stdin.write(MAINTAINER_KEYS.encode('utf-8'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700480 proc.stdin.close()
481
482 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400483 print('fatal: registering repo maintainer keys failed', file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700484 sys.exit(1)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400485 print()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700486
Mike Frysinger3164d402019-11-11 05:40:22 -0500487 with open(os.path.join(home_dot_repo, 'keyring-version'), 'w') as fd:
488 fd.write('.'.join(map(str, KEYRING_VERSION)) + '\n')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700489 return True
490
491
492def _SetConfig(local, name, value):
493 """Set a git configuration option to the specified value.
494 """
495 cmd = [GIT, 'config', name, value]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700496 if subprocess.Popen(cmd, cwd=local).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700497 raise CloneFailure()
498
499
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700500def _InitHttp():
501 handlers = []
502
Sarah Owens1f7627f2012-10-31 09:21:55 -0700503 mgr = urllib.request.HTTPPasswordMgrWithDefaultRealm()
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700504 try:
505 import netrc
506 n = netrc.netrc()
507 for host in n.hosts:
508 p = n.hosts[host]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700509 mgr.add_password(p[1], 'http://%s/' % host, p[0], p[2])
Xiaodong Xuae0a36c2012-01-31 11:10:09 +0800510 mgr.add_password(p[1], 'https://%s/' % host, p[0], p[2])
David Pursehouse65b0ba52018-06-24 16:21:51 +0900511 except:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700512 pass
Sarah Owens1f7627f2012-10-31 09:21:55 -0700513 handlers.append(urllib.request.HTTPBasicAuthHandler(mgr))
514 handlers.append(urllib.request.HTTPDigestAuthHandler(mgr))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700515
516 if 'http_proxy' in os.environ:
517 url = os.environ['http_proxy']
Sarah Owens1f7627f2012-10-31 09:21:55 -0700518 handlers.append(urllib.request.ProxyHandler({'http': url, 'https': url}))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700519 if 'REPO_CURL_VERBOSE' in os.environ:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700520 handlers.append(urllib.request.HTTPHandler(debuglevel=1))
521 handlers.append(urllib.request.HTTPSHandler(debuglevel=1))
522 urllib.request.install_opener(urllib.request.build_opener(*handlers))
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700523
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700524
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700525def _Fetch(url, local, src, quiet):
526 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400527 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700528
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700529 cmd = [GIT, 'fetch']
530 if quiet:
531 cmd.append('--quiet')
532 err = subprocess.PIPE
533 else:
534 err = None
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700535 cmd.append(src)
536 cmd.append('+refs/heads/*:refs/remotes/origin/*')
Xin Li6e538442018-12-10 11:33:16 -0800537 cmd.append('+refs/tags/*:refs/tags/*')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700538
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700539 proc = subprocess.Popen(cmd, cwd=local, stderr=err)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700540 if err:
541 proc.stderr.read()
542 proc.stderr.close()
543 if proc.wait() != 0:
544 raise CloneFailure()
545
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700546
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700547def _DownloadBundle(url, local, quiet):
548 if not url.endswith('/'):
549 url += '/'
550 url += 'clone.bundle'
551
552 proc = subprocess.Popen(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700553 [GIT, 'config', '--get-regexp', 'url.*.insteadof'],
554 cwd=local,
555 stdout=subprocess.PIPE)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700556 for line in proc.stdout:
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400557 line = line.decode('utf-8')
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700558 m = re.compile(r'^url\.(.*)\.insteadof (.*)$').match(line)
559 if m:
560 new_url = m.group(1)
561 old_url = m.group(2)
562 if url.startswith(old_url):
563 url = new_url + url[len(old_url):]
564 break
565 proc.stdout.close()
566 proc.wait()
567
568 if not url.startswith('http:') and not url.startswith('https:'):
569 return False
570
571 dest = open(os.path.join(local, '.git', 'clone.bundle'), 'w+b')
572 try:
573 try:
Sarah Owens1f7627f2012-10-31 09:21:55 -0700574 r = urllib.request.urlopen(url)
575 except urllib.error.HTTPError as e:
John Törnblomd3ddcdb2015-08-12 20:12:51 +0200576 if e.code in [401, 403, 404, 501]:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700577 return False
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400578 print('fatal: Cannot get %s' % url, file=sys.stderr)
579 print('fatal: HTTP error %s' % e.code, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700580 raise CloneFailure()
Sarah Owens1f7627f2012-10-31 09:21:55 -0700581 except urllib.error.URLError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400582 print('fatal: Cannot get %s' % url, file=sys.stderr)
583 print('fatal: error %s' % e.reason, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700584 raise CloneFailure()
585 try:
586 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400587 print('Get %s' % url, file=sys.stderr)
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700588 while True:
589 buf = r.read(8192)
Mike Frysinger1b9adab2019-07-04 17:54:54 -0400590 if not buf:
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700591 return True
592 dest.write(buf)
593 finally:
594 r.close()
595 finally:
596 dest.close()
597
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700598
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700599def _ImportBundle(local):
600 path = os.path.join(local, '.git', 'clone.bundle')
601 try:
602 _Fetch(local, local, path, True)
603 finally:
604 os.remove(path)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700605
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700606
Hu xiuyun9711a982015-12-11 11:16:41 +0800607def _Clone(url, local, quiet, clone_bundle):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700608 """Clones a git repository to a new subdirectory of repodir
609 """
610 try:
611 os.mkdir(local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700612 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400613 print('fatal: cannot make %s directory: %s' % (local, e.strerror),
614 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700615 raise CloneFailure()
616
617 cmd = [GIT, 'init', '--quiet']
618 try:
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700619 proc = subprocess.Popen(cmd, cwd=local)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700620 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400621 print(file=sys.stderr)
622 print("fatal: '%s' is not available" % GIT, file=sys.stderr)
623 print('fatal: %s' % e, file=sys.stderr)
624 print(file=sys.stderr)
625 print('Please make sure %s is installed and in your path.' % GIT,
626 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700627 raise CloneFailure()
628 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400629 print('fatal: could not create %s' % local, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700630 raise CloneFailure()
631
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700632 _InitHttp()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700633 _SetConfig(local, 'remote.origin.url', url)
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700634 _SetConfig(local,
635 'remote.origin.fetch',
636 '+refs/heads/*:refs/remotes/origin/*')
Hu xiuyun9711a982015-12-11 11:16:41 +0800637 if clone_bundle and _DownloadBundle(url, local, quiet):
Shawn O. Pearcef322b9a2011-09-19 14:50:58 -0700638 _ImportBundle(local)
Dan Willemsenfee390e2015-09-02 12:36:30 -0700639 _Fetch(url, local, 'origin', quiet)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700640
641
642def _Verify(cwd, branch, quiet):
643 """Verify the branch has been signed by a tag.
644 """
645 cmd = [GIT, 'describe', 'origin/%s' % branch]
646 proc = subprocess.Popen(cmd,
647 stdout=subprocess.PIPE,
648 stderr=subprocess.PIPE,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700649 cwd=cwd)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400650 cur = proc.stdout.read().strip().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700651 proc.stdout.close()
652
653 proc.stderr.read()
654 proc.stderr.close()
655
656 if proc.wait() != 0 or not cur:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400657 print(file=sys.stderr)
658 print("fatal: branch '%s' has not been signed" % branch, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700659 raise CloneFailure()
660
661 m = re.compile(r'^(.*)-[0-9]{1,}-g[0-9a-f]{1,}$').match(cur)
662 if m:
663 cur = m.group(1)
664 if not quiet:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400665 print(file=sys.stderr)
666 print("info: Ignoring branch '%s'; using tagged release '%s'"
667 % (branch, cur), file=sys.stderr)
668 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700669
Shawn O. Pearcef18cb762010-12-07 11:41:05 -0800670 env = os.environ.copy()
Dāvis Mosāns631d0ec2016-07-16 21:11:11 +0300671 try:
672 env['GNUPGHOME'] = gpg_dir
673 except UnicodeEncodeError:
674 env['GNUPGHOME'] = gpg_dir.encode()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700675
676 cmd = [GIT, 'tag', '-v', cur]
677 proc = subprocess.Popen(cmd,
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700678 stdout=subprocess.PIPE,
679 stderr=subprocess.PIPE,
680 cwd=cwd,
681 env=env)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400682 out = proc.stdout.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700683 proc.stdout.close()
684
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400685 err = proc.stderr.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700686 proc.stderr.close()
687
688 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400689 print(file=sys.stderr)
690 print(out, file=sys.stderr)
691 print(err, file=sys.stderr)
692 print(file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700693 raise CloneFailure()
694 return '%s^0' % cur
695
696
697def _Checkout(cwd, branch, rev, quiet):
698 """Checkout an upstream branch into the repository and track it.
699 """
700 cmd = [GIT, 'update-ref', 'refs/heads/default', rev]
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700701 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700702 raise CloneFailure()
703
704 _SetConfig(cwd, 'branch.default.remote', 'origin')
705 _SetConfig(cwd, 'branch.default.merge', 'refs/heads/%s' % branch)
706
707 cmd = [GIT, 'symbolic-ref', 'HEAD', 'refs/heads/default']
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700708 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700709 raise CloneFailure()
710
711 cmd = [GIT, 'read-tree', '--reset', '-u']
712 if not quiet:
713 cmd.append('-v')
714 cmd.append('HEAD')
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700715 if subprocess.Popen(cmd, cwd=cwd).wait() != 0:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700716 raise CloneFailure()
717
718
719def _FindRepo():
720 """Look for a repo installation, starting at the current directory.
721 """
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200722 curdir = os.getcwd()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700723 repo = None
724
Anthony Newnamdf14a702011-01-09 17:31:57 -0800725 olddir = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200726 while curdir != '/' \
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700727 and curdir != olddir \
728 and not repo:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200729 repo = os.path.join(curdir, repodir, REPO_MAIN)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700730 if not os.path.isfile(repo):
731 repo = None
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200732 olddir = curdir
733 curdir = os.path.dirname(curdir)
734 return (repo, os.path.join(curdir, repodir))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700735
736
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700737class _Options(object):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700738 help = False
739
740
741def _ParseArguments(args):
742 cmd = None
743 opt = _Options()
744 arg = []
745
Sarah Owensa6053d52012-11-01 13:36:50 -0700746 for i in range(len(args)):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700747 a = args[i]
748 if a == '-h' or a == '--help':
749 opt.help = True
750
751 elif not a.startswith('-'):
752 cmd = a
753 arg = args[i + 1:]
754 break
755 return cmd, opt, arg
756
757
758def _Usage():
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700759 gitc_usage = ""
760 if get_gitc_manifest_dir():
761 gitc_usage = " gitc-init Initialize a GITC Client.\n"
762
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400763 print(
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700764 """usage: repo COMMAND [ARGS]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700765
766repo is not yet installed. Use "repo init" to install it here.
767
768The most commonly used repo commands are:
769
770 init Install repo in the current working directory
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700771""" + gitc_usage +
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700772 """ help Display detailed help on a command
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700773
774For access to the full online help, install repo ("repo init").
Mike Frysinger35159ab2019-06-13 00:07:13 -0400775""")
776 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700777
778
779def _Help(args):
780 if args:
781 if args[0] == 'init':
782 init_optparse.print_help()
Trond Norbyed3fd5372011-01-03 11:35:15 +0100783 sys.exit(0)
Dan Willemsen9ff2ece2015-08-31 15:45:06 -0700784 elif args[0] == 'gitc-init':
785 _GitcInitOptions(init_optparse)
786 init_optparse.print_help()
787 sys.exit(0)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700788 else:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400789 print("error: '%s' is not a bootstrap command.\n"
790 ' For access to online help, install repo ("repo init").'
791 % args[0], file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700792 else:
793 _Usage()
794 sys.exit(1)
795
796
797def _NotInstalled():
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400798 print('error: repo is not installed. Use "repo init" to install it here.',
799 file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700800 sys.exit(1)
801
802
803def _NoCommands(cmd):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400804 print("""error: command '%s' requires repo to be installed first.
805 Use "repo init" to install it here.""" % cmd, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700806 sys.exit(1)
807
808
809def _RunSelf(wrapper_path):
810 my_dir = os.path.dirname(wrapper_path)
811 my_main = os.path.join(my_dir, 'main.py')
812 my_git = os.path.join(my_dir, '.git')
813
814 if os.path.isfile(my_main) and os.path.isdir(my_git):
Shawn O. Pearcec8a300f2009-05-18 13:19:57 -0700815 for name in ['git_config.py',
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700816 'project.py',
817 'subcmds']:
818 if not os.path.exists(os.path.join(my_dir, name)):
819 return None, None
820 return my_main, my_git
821 return None, None
822
823
824def _SetDefaultsTo(gitdir):
825 global REPO_URL
826 global REPO_REV
827
828 REPO_URL = gitdir
829 proc = subprocess.Popen([GIT,
830 '--git-dir=%s' % gitdir,
831 'symbolic-ref',
832 'HEAD'],
Mark E. Hamilton4088eb42016-02-10 10:44:30 -0700833 stdout=subprocess.PIPE,
834 stderr=subprocess.PIPE)
Mike Frysinger9100f7f2019-09-11 03:58:36 -0400835 REPO_REV = proc.stdout.read().strip().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700836 proc.stdout.close()
837
838 proc.stderr.read()
839 proc.stderr.close()
840
841 if proc.wait() != 0:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400842 print('fatal: %s has no current branch' % gitdir, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700843 sys.exit(1)
844
845
846def main(orig_args):
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700847 cmd, opt, args = _ParseArguments(orig_args)
848
Dan Willemsen745b4ad2015-10-06 15:23:19 -0700849 repo_main, rel_repo_dir = None, None
850 # Don't use the local repo copy, make sure to switch to the gitc client first.
851 if cmd != 'gitc-init':
852 repo_main, rel_repo_dir = _FindRepo()
853
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700854 wrapper_path = os.path.abspath(__file__)
855 my_main, my_git = _RunSelf(wrapper_path)
856
Simran Basi8ce50412015-08-28 14:25:44 -0700857 cwd = os.getcwd()
Dan Willemsen2487cb72015-08-31 15:45:06 -0700858 if get_gitc_manifest_dir() and cwd.startswith(get_gitc_manifest_dir()):
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400859 print('error: repo cannot be used in the GITC local manifest directory.'
860 '\nIf you want to work on this GITC client please rerun this '
861 'command from the corresponding client under /gitc/',
862 file=sys.stderr)
Simran Basi8ce50412015-08-28 14:25:44 -0700863 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200864 if not repo_main:
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700865 if opt.help:
866 _Usage()
867 if cmd == 'help':
868 _Help(args)
869 if not cmd:
870 _NotInstalled()
Simran Basi1efc2b42015-08-05 15:04:22 -0700871 if cmd == 'init' or cmd == 'gitc-init':
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700872 if my_git:
873 _SetDefaultsTo(my_git)
874 try:
Simran Basi1efc2b42015-08-05 15:04:22 -0700875 _Init(args, gitc_init=(cmd == 'gitc-init'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700876 except CloneFailure:
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200877 path = os.path.join(repodir, S_repo)
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400878 print("fatal: cloning the git-repo repository failed, will remove "
879 "'%s' " % path, file=sys.stderr)
Sebastian Schuberth27226e72016-10-28 14:27:43 +0200880 shutil.rmtree(path, ignore_errors=True)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700881 sys.exit(1)
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200882 repo_main, rel_repo_dir = _FindRepo()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700883 else:
884 _NoCommands(cmd)
885
886 if my_main:
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200887 repo_main = my_main
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700888
David Pursehouse685f0802012-11-14 08:34:39 +0900889 ver_str = '.'.join(map(str, VERSION))
anatoly techtonik3a2a59e2013-09-21 19:29:10 +0300890 me = [sys.executable, repo_main,
Mickaël Salaün2f6ab7f2012-09-30 00:37:55 +0200891 '--repo-dir=%s' % rel_repo_dir,
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700892 '--wrapper-version=%s' % ver_str,
893 '--wrapper-path=%s' % wrapper_path,
894 '--']
895 me.extend(orig_args)
896 me.extend(extra_args)
897 try:
Renaud Paquay35d22212016-11-01 11:24:52 -0700898 if platform.system() == "Windows":
899 sys.exit(subprocess.call(me))
900 else:
901 os.execv(sys.executable, me)
Sarah Owensa5be53f2012-09-09 15:37:57 -0700902 except OSError as e:
Mike Frysingerc92ce5c2019-06-13 01:14:23 -0400903 print("fatal: unable to start %s" % repo_main, file=sys.stderr)
904 print("fatal: %s" % e, file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700905 sys.exit(148)
906
907
908if __name__ == '__main__':
909 main(sys.argv[1:])